import mysql.connector
from mysql.connector import pooling
import redis
import json
from datetime import datetime, date
from decimal import Decimal
from config import Config
from flask import Flask, jsonify, render_template
from flask_socketio import SocketIO
import threading



# MySQL连接池配置
mysql_config = Config.mysql_config

# Redis连接配置
redis_config = Config.redis_config

# 创建连接池和Redis客户端
mysql_pool = pooling.MySQLConnectionPool(pool_name="mypool", pool_size=5, **mysql_config)
redis_client = redis.StrictRedis(**redis_config)
socketio = SocketIO()

# JSON编码器，处理datetime和Decimal
def custom_json_serializer(obj):
    if isinstance(obj, (datetime, date)):
        return obj.strftime('%Y-%m-%d %H:%M:%S')
    elif isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Type {type(obj)} not serializable")

def get_mysql_data():
    """
    获取MySQL数据库中的所有表的数据，并同步到Redis。
    """
    from handle.logger import logger  # 局部调用 logger

    conn = mysql_pool.get_connection()
    cursor = conn.cursor()

    try:
        # 获取数据库中所有表
        cursor.execute("SHOW TABLES")
        tables = cursor.fetchall()
        existing_tables = {table[0] for table in tables}

        # 明确要求同步的表
        required_tables = {"user", "reports"}

        # 将所有表名合并，确保 'user' 和 'reports' 包括在内
        all_tables = existing_tables.union(required_tables)

        # 清空Redis数据库
        try:
            redis_client.flushdb()
            logger.info("Redis缓存已清空")
            socketio.emit('log', {'data': "Redis缓存已清空"})
        except Exception as e:
            logger.error(f"清空Redis失败: {e}")
            socketio.emit('log', {'data': f"清空Redis失败: {e}"})

        pipeline = redis_client.pipeline()  # 使用 Redis 管道

        for table_name in all_tables:
            try:
                logger.debug(f"开始同步表 {table_name}")
                cursor.execute(f"SELECT * FROM {table_name}")
                rows = cursor.fetchall()
                columns = [desc[0] for desc in cursor.description]  # 获取列名

                # 组合成字典格式的记录
                formatted_data = [dict(zip(columns, row)) for row in rows]

                # 即使表无数据，也确保在 Redis 中占位
                if not formatted_data:
                    logger.warning(f"表 {table_name} 无数据")
                    pipeline.set(table_name, "[]")  # 空表存储为空列表的 JSON
                else:
                    data = json.dumps(formatted_data, default=custom_json_serializer, ensure_ascii=False)
                    pipeline.set(table_name, data)
                    logger.info(f"表 {table_name} 同步完成")

                socketio.emit('log', {'data': f"表 {table_name} 同步完成!"})
            except Exception as e:
                logger.error(f"表 {table_name} 同步失败: {e}")
                socketio.emit('log', {'data': f"表 {table_name} 同步失败: {e}"})

        # 执行Redis管道操作
        try:
            pipeline.execute()
            logger.info("所有数据同步完成")
            socketio.emit('log', {'data': "所有数据同步完成"})
            logger.info("开始格式化User表")
            socketio.emit('log', {'data': "开始格式化User表"})
        except Exception as e:
            logger.error(f"Redis写入失败: {e}")
            socketio.emit('log', {'data': f"Redis写入失败: {e}"})

    except Exception as e:
        logger.critical(f"数据库同步发生致命错误: {e}")
        socketio.emit('log', {'data': f"数据库同步发生致命错误: {e}"})
    finally:
        cursor.close()
        conn.close()

def sync_data_background():
    """
    异步执行MySQL到Redis的同步任务。
    """
    thread = threading.Thread(target=get_mysql_data)
    thread.start()
    return thread
